﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Text;
using DAL;
using System.Transactions;
using System.ComponentModel;

namespace BOL
{
    [Serializable]
    public class NotaSalidaBL
    {


        public void verificacierreKardex(dbGestionDataContext _db, 
                                         DateTime fecha, 
                                         int idAlmacen)
        {
            var q = from a in _db.SaldoKardexes
                    where
                    a.idAlmacen == idAlmacen
                    & a.anio == fecha.Year
                    & a.mes == fecha.Month
                    select a;

            if (q.Count() > 0)
            {
                throw new Exception("Existe Cierre de Kardex");
            }
        }


        public int Add(
                        DateTime fecha,
                        int	idMotivo,
                        string	documentoRef,
                        int	idDocumentoTipo,
                        int	idObra,
                        string empleadoSolicita,
                        int	idAutorizado,
                        int?	idUnidTrabajo,
                        int	idAlmacen,
                        string observacion,
                        int? idAlmacenDestino,
                        DataSet dsColeccion)
        {

            using (TransactionScope ts = new TransactionScope())
            {
                dbGestionDataContext _db = new dbGestionDataContext(Parametros.strConnString);
                int idEmpleadoEmisor = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());

                //valida fecha de cierre 
                //--------------------
                bool acceso = new FormularioAcceso().VerificarAcceso(_db,
                    idEmpleadoEmisor,
                    8, //Nota Salida
                    idObra,
                    2); //creacion
                //-------------------------     

                verificacierreKardex(_db,fecha, idAlmacen);

              

                NotaSalida ni = new NotaSalida();
                ni.Add(_db,
                    ni.getCorrelativo(_db, idAlmacen),
                        fecha,
                        idMotivo,
                        documentoRef,
                        idDocumentoTipo,
                        idObra,
                        empleadoSolicita,
                        idAutorizado,
                        idUnidTrabajo,
                        idAlmacen,
                        observacion,
                        idEmpleadoEmisor,
                        idAlmacenDestino);

                NotaSalidaItemInfo iteminfo = new NotaSalidaItemInfo();
                if (dsColeccion.Tables[iteminfo.GetType().Name].Rows.Count == 0)
                {
                    throw new Exception("Ingrese informacion de Items");
                }
                foreach (DataRow item in dsColeccion.Tables[iteminfo.GetType().Name].Rows)
                {

                    if (item.RowState == DataRowState.Added)
                    {
                        iteminfo = (NotaSalidaItemInfo)UtilityExtensions.Util.DataRowToEntidad(item,
                                                              iteminfo.GetType());
                        NotaSalidaItem nitem = new NotaSalidaItem();
                        nitem.Add(_db,
                                   ni.idInternal,
                                   iteminfo.idInsumo,
                                   iteminfo.cantidad);


                        ////registramos en el kardex
                        ////actulizamos el kardex solo los item  en la nota de salida
                        //var q = _db.Kardexes.Where(p => p.idInsumo == iteminfo.idInsumo &
                        //                                    p.idAlmacen == idAlmacen & 
                        //                                    p.mes == fecha.Month & 
                        //                                    p.anio == fecha.Year);
                        ////si no existe se registra
                        //if (q.Count() == 0)
                        //{
                        //    Kardex karde = new Kardex();
                        //    karde.Add(_db,
                        //            iteminfo.idInsumo,
                        //            Convert.ToInt16(fecha.Year),
                        //            Convert.ToInt16(fecha.Month),
                        //            idAlmacen,
                        //            fecha,
                        //            0,
                        //            iteminfo.cantidad);
                        //}
                        //else
                        //{
                        //    //actualizo el valor
                        //    if (q.Count() > 1) { throw new Exception("Existe mas de un valor,Verificar"); }
                        //    Kardex karde = q.First();
                        //    karde.UpdateSalida(_db);

                        //}

                        
                    }
                }
                ts.Complete();
                return ni.idInternal;

            }
        }

        

        public bool Delete(int idNotaSalida)
        {
            using (TransactionScope ts = new TransactionScope())
            {
                bool result = false;
                using (dbGestionDataContext _db = new dbGestionDataContext(Parametros.strConnString))
                {
                    NotaSalida ni = _db.NotaSalidas.Single(p => p.idInternal == idNotaSalida);
                    int idEmpleadoEmisor = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());
                    //--------------------
                    bool acceso = new FormularioAcceso().VerificarAcceso(_db,
                        idEmpleadoEmisor,
                        8, //Nota salida
                        ni.Almacen.idObra.Value,
                        4); //creacion
                    //-------------------------     



                    //valida fecha de cierre 

                    verificacierreKardex(_db, ni.fecha, ni.idAlmacen);
                    var q = from a in _db.NotaSalidaItems
                            where a.idNotaSalida == idNotaSalida
                            select a;

                    //foreach (var item in q)
                    //{
                    //    //actulizamos el kardex solo los item  en la nota de ingreso
                    //    var ka = _db.Kardexes.Where(p => p.idInsumo == item.idInsumo &
                    //                                    p.idAlmacen == ni.idAlmacen &
                    //                                    p.mes == ni.fecha.Month &
                    //                                    p.anio == ni.fecha.Year);
                    //    if (ka.Count() == 0)
                    //    {
                    //        throw new Exception("Verifique que Kardex antes de eliminar");
                    //    }

                    //    Kardex karde = ka.First();
                    //    karde.UpdateSalida(_db);
                    //}
                   

                    _db.NotaSalidaItems.DeleteAllOnSubmit(q);
                    _db.NotaSalidas.DeleteOnSubmit(ni);
                    _db.SubmitChanges();
                    result = true;
                }

                ts.Complete();
                return result;
            }



        }

        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public NotaSalidaInfo Load(int idNotaSalida)
        {

            var q = from a in DbUtil.Db.NotaSalidas
                    where a.idInternal == idNotaSalida
                    select new NotaSalidaInfo
                    {
                        almacen=a.Almacen.descripcion,
                        autorizado=a.Empleado.descripcion,
                        documentoRef=a.documentoRef,
                        documentoTipo=a.DocumentoTipo.abreviacion,
                        fechaStr=a.fecha.ToShortDateString(),
                        fechaCre=a.fechaCre,
                        fechaMod=a.fechaMod,
                        idAlmacen=a.idAlmacen,
                        idAutorizado=a.idAutorizado,
                        motivo=a.MotivoItem.descripcion,
                        idDocumentoTipo=a.idDocumentoTipo,
                        empleadoSolicita=a.empleadoSolicita,
                    idInternal=a.idInternal,
                    idMotivo=a.idMotivo,
                    idObra=a.idObra,
                    idUnidTrabajo=a.idUnidTrabajo,
                    numDocumento=a.numDocumento,
                    observacion=a.observacion,
                    unidTrabajo = (a.idUnidTrabajo==null)?"":a.UnidadTrabajo.descripcion,
                    usuarioCre=a.Empleado1.descripcion,
                    usuarioMod=a.Empleado2.descripcion };


            return q.First();


        }



        int _count;
        public int Count(int idAlmacen,
                           int  idMotivo,
                           DateTime? fechaInicio,
                           DateTime? fechaFin,
                           string documentoRef,
                           string numDocumento,
                           int startRowIndex,
                           int maximumRows,
                           string sortExpression)
        {
            return _count;
        }

        public int Count(int idAlmacenDestino,
                         int idAlmacenOrigen,
                         int startRowIndex,
                         int maximumRows,
                         string sortExpression)
        {
            return _count;
        }

        private IQueryable<NotaSalidaListInfo> ApplySort(IQueryable<NotaSalidaListInfo> q,
                                                string sortExpression)
        {
            switch (sortExpression)
            {
                case "documentoRef":
                    q = q.OrderBy(b => b.documentoRef);
                    break;
                case "documentoRef DESC":
                    q = q.OrderByDescending(b => b.documentoRef);
                    break;
                case "documentoTipo":
                    q = q.OrderBy(b => b.documentoTipo);
                    break;
                case "documentoTipo DESC":
                    q = q.OrderByDescending(b => b.documentoTipo);
                    break;
                case "empleadoSolicita":
                    q = q.OrderBy(b => b.empleadoSolicita);
                    break;
                case "empleadoSolicita DESC":
                    q = q.OrderByDescending(b => b.empleadoSolicita);
                    break;

                case "fecha":
                    q = q.OrderBy(b => b.fecha);
                    break;
                case "fecha DESC":
                    q = q.OrderByDescending(b => b.fecha);
                    break;


                case "motivo":
                    q = q.OrderBy(b => b.motivo);
                    break;
                case "motivo DESC":
                    q = q.OrderByDescending(b => b.motivo);
                    break;


                case "numDocumento":
                    q = q.OrderBy(b => b.numDocumento);
                    break;
                case "numDocumento DESC":
                    q = q.OrderByDescending(b => b.numDocumento);
                    break;
                case "observacion":
                    q = q.OrderBy(b => b.observacion);
                    break;
                case "observacion DESC":
                    q = q.OrderByDescending(b => b.observacion);
                    break;
                case "unidTrabajo":
                    q = q.OrderBy(b => b.unidTrabajo);
                    break;
                case "unidTrabajo DESC":
                    q = q.OrderByDescending(b => b.unidTrabajo);
                    break;
                default:
                    q = q.OrderByDescending(b=>b.numDocumento).OrderByDescending(b => b.fecha);
                    break;
            }
            return q;
        }


        private IQueryable<NotaSalidaListInfo> ApplySelect_NotaSalidaListInfo()
        {
            var q = from a in DbUtil.Db.NotaSalidas
                    select new NotaSalidaListInfo
                    {
                        almacen = a.Almacen.descripcion,
                        autorizado = a.Empleado1.descripcion,
                        documentoRef = a.documentoRef,
                        documentoTipo = a.DocumentoTipo.abreviacion,
                        empleadoSolicita = a.Empleado.descripcion,
                        fecha = a.fecha,
                        fechaStr=a.fecha.ToShortDateString(),
                        idAlmacen = a.idAlmacen,
                        idInternal = a.idInternal,
                        motivo = a.MotivoItem.descripcion,
                        numDocumento = a.numDocumento,
                        observacion = a.observacion,
                        unidTrabajo = a.UnidadTrabajo.descripcion,
                        idObra = a.idObra ,
                        idMotivo=a.idMotivo ,
                        idAlmacenDestino=a.idAlmacenDest,
                        idObraDestino=a.idAlmacenDest!=null?a.Almacen1.idObra:null,
                    };
            return q;
        }

       

        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public List<NotaSalidaListInfo> getNotaSalidaFiltroList(int idAlmacen, int idMotivo, 
            DateTime fechaInicio, 
            DateTime fechaFin,
            string documentoRef,
            string numDocumento,
            int startRowIndex,
           int maximumRows,
           string sortExpression)
        {
            if (documentoRef==null)
                documentoRef = "";
            if (numDocumento == null)
                numDocumento = "";



            var q = ApplySelect_NotaSalidaListInfo();

            q = q.Where(a => a.idAlmacen == idAlmacen &
                        (idMotivo==0?a.idMotivo!=0:a.idMotivo==idMotivo) &
                        a.fecha>=fechaInicio &
                        a.fecha <= fechaFin.AddDays(1)&
                        a.documentoRef.Contains(documentoRef) &
                        a.numDocumento.Contains(numDocumento));

            _count = q.Count();

            q = ApplySort(q, sortExpression);
            return q.Skip(startRowIndex).Take(maximumRows).ToList();

        }



        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public List<NotaSalidaListInfo> getNotaSalidaPentList(int idAlmacenDestino,
                                                            int idAlmacenOrigen,
                                                           int startRowIndex,
                                                           int maximumRows,
                                                           string sortExpression)
          {


             var q = (from a in DbUtil.Db.NotaSalidaItems
                      where
                      a.NotaSalida.idAlmacenDest == idAlmacenDestino &
                      idAlmacenOrigen == 0 ? a.NotaSalida.idAlmacen != 0 : a.NotaSalida.idAlmacen == idAlmacenOrigen &
                      (a.cantidad-a.cantidadRecep>0) &
                      a.NotaSalida.idMotivo==12 
                    select new NotaSalidaListInfo
                    {
                        almacen = a.NotaSalida.Almacen.descripcion,
                        autorizado = a.NotaSalida.Empleado1.descripcion,
                        documentoRef = a.NotaSalida.documentoRef,
                        documentoTipo = a.NotaSalida.DocumentoTipo.abreviacion,
                        empleadoSolicita = a.NotaSalida.Empleado.descripcion,
                        fecha = a.NotaSalida.fecha,
                        fechaStr=a.NotaSalida.fecha.ToShortDateString(),
                        idAlmacen = a.NotaSalida.idAlmacen,
                        idInternal = a.NotaSalida.idInternal,
                        motivo = a.NotaSalida.MotivoItem.descripcion,
                        numDocumento = a.NotaSalida.numDocumento,
                        observacion = a.NotaSalida.observacion,
                        unidTrabajo = a.NotaSalida.UnidadTrabajo.descripcion,
                        idObra = a.NotaSalida.idObra,
                        idMotivo = a.NotaSalida.idMotivo,
                        idAlmacenDestino = a.NotaSalida.idAlmacenDest,
                        idObraDestino = a.NotaSalida.idAlmacenDest != null ? a.NotaSalida.Almacen1.idObra : null,
                    }).Distinct();
           



            _count = q.Count();

            q = ApplySort(q, sortExpression);
            return q.Skip(startRowIndex).Take(maximumRows).ToList();

        }



        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public List<NotaSalidaListInfo> GetNotaSalidaList(int idObra)
        {
            var q = from a in DbUtil.Db.NotaSalidas
                    where a.idObra == idObra
                    select new NotaSalidaListInfo
                    {
                        almacen = a.Almacen.descripcion,
                        autorizado = a.Empleado1.descripcion,
                        documentoRef = a.documentoRef,
                        documentoTipo = a.DocumentoTipo.abreviacion,
                        empleadoSolicita = a.Empleado.descripcion,
                        fecha = a.fecha,
                        idAlmacen = a.idAlmacen,
                        idInternal = a.idInternal,
                        motivo = a.MotivoItem.descripcion,
                        numDocumento = a.numDocumento,
                        observacion = a.observacion,
                        unidTrabajo = a.UnidadTrabajo.descripcion,
                        idObra=a.idObra
                    };

            return q.ToList();
        }



        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public List<NotaSalidaItemInfo> GetNotaSalidaItem(int idNotaSalida)
        {
            var q = from a in DbUtil.Db.NotaSalidaItems
                    where a.idNotaSalida == idNotaSalida
                    select new NotaSalidaItemInfo
                        {
                            idInternal =a.idInternal,
                            idInsumo =a.idInsumo,
                            codigo =a.Insumo.codigo,
                            descripcion =a.Insumo.descripcion,
                            unidad =a.Insumo.InsumoUnidad.abreviacion,
                            cantidad =a.cantidad
                                        };

            return q.ToList();
        }



        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public List<NotaSalidaItemInfo> GetNotaSalidaFromNotaIngreso (int idNotaIngreso)
        {
            var q = from a in DbUtil.Db.NotaIngresoItems
                    where a.idNotaIngreso == idNotaIngreso
                    select new NotaSalidaItemInfo
                    {
                        idInternal = a.idInternal,
                        idInsumo = a.idInsumo,
                        codigo = a.Insumo.codigo,
                        descripcion = a.Insumo.descripcion,
                        unidad = a.Insumo.InsumoUnidad.abreviacion,
                        cantidad = a.cantidad.Value
                    };

            return q.ToList();
        }
     
    }
}
